{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true,
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "# Create a Marquee Portfolio with GS Quant\n",
    "\n",
    "The Marquee Portfolio Service provides a powerful framework for uploading portfolio positions and retrieving analytics including historical performance, factor risk exposure, ESG analytics, and more. GS Quant makes operating the suite of Portfolio Service API's intuitive and fast.\n",
    "\n",
    "## Permission Prerequisites\n",
    "\n",
    "To execute all the code in this tutorial, you will need the following application scopes:\n",
    "- **read_product_data**\n",
    "- **read_financial_data**\n",
    "- **modify_product_data** (must be requested)\n",
    "- **modify_financial_data** (must be requested)\n",
    "- **run_analytics** (must be requested)\n",
    "- **read_user_profile**\n",
    "\n",
    "If you are not yet permissioned for these scopes, please request them on your [My Applications Page](https://developer.gs.com/go/apps/view). If you have any other questions please reach out to the [Marquee sales team](mailto:gs-marquee-sales@gs.com).\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "## Step 1: Authenticate and Initialize Your Session\n",
    "\n",
    "First you will import the necessary modules and add your client id and client secret."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "import datetime as dt\n",
    "\n",
    "from gs_quant.entities.entitlements import Entitlements, EntitlementBlock, User\n",
    "from gs_quant.markets.portfolio import Portfolio\n",
    "from gs_quant.markets.portfolio_manager import PortfolioManager\n",
    "from gs_quant.markets.report import CustomAUMDataPoint\n",
    "from gs_quant.markets.position_set import Position, PositionSet\n",
    "from gs_quant.session import GsSession, Environment\n",
    "from gs_quant.target.portfolios import RiskAumSource\n",
    "\n",
    "client = 'ENTER CLIENT ID'\n",
    "secret = 'ENTER CLIENT SECRET'\n",
    "\n",
    "GsSession.use(\n",
    "    Environment.PROD,\n",
    "    client_id=client,\n",
    "    client_secret=secret,\n",
    "    scopes=('read_product_data read_financial_data modify_product_data modify_financial_data run_analytics read_user_profile',)\n",
    ")\n",
    "\n",
    "print('GS Session initialized.')"
   ]
  },
  {
   "cell_type": "markdown",
   "source": [
    "## Step 2: Create the Portfolio\n",
    "\n",
    "The first step is to create a new, empty portfolio in Marquee."
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "portfolio = Portfolio(name='My New Portfolio')\n",
    "portfolio.save()\n",
    "\n",
    "print(f\"Created portfolio '{portfolio.name}' with ID: {portfolio.id}\")"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "Once your portfolio has been saved to Marquee, the `PortfolioManager` class allows users to interact with their Marquee portfolios directly from GS Quant. We will be using `PortfolioManager` to update portfolio positions, entitlements, update custom AUM, and run reports.\n",
    "\n",
    "## Step 3: Define Portfolio Entitlements\n",
    "\n",
    "By default, an application will have all entitlement permissions to a portfolio it makes. However, if you would like to share the portfolio with others, either Marquee users or other applications, you will need to specify them in the entitlements parameter of the portfolio. Let's walk through how we convert a list of admin and viewer emails into an `Entitlements` object:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    },
    "scrolled": false
   },
   "outputs": [],
   "source": [
    "portfolio_admin_emails = ['LIST OF ADMIN EMAILS']\n",
    "portfolio_viewer_emails = ['LIST OF VIEWER EMAILS']\n",
    "\n",
    "pm = PortfolioManager(portfolio.id)\n",
    "pm.share(portfolio_admin_emails, admin=True)\n",
    "pm.share(portfolio_viewer_emails, admin=False)\n",
    "\n",
    "print(f\"Updated entitlements for '{portfolio.name}'\")"
   ]
  },
  {
   "cell_type": "markdown",
   "source": [
    "If you'd like more control on the entitlements (e.g. you want to remove someone), you can use the `Entitlements` class directly. Here's an example:"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "portfolio_admin_emails = ['LIST OF ADMIN EMAILS']\n",
    "portfolio_viewer_emails = ['LIST OF VIEWER EMAILS']\n",
    "\n",
    "admin_entitlements = EntitlementBlock(users=User.get_many(emails=portfolio_admin_emails))\n",
    "view_entitlements = EntitlementBlock(users=User.get_many(emails=portfolio_viewer_emails))\n",
    "\n",
    "entitlements = Entitlements(\n",
    "    view=view_entitlements,\n",
    "    admin=admin_entitlements\n",
    ")\n",
    "\n",
    "print(f'Entitlements:\\n{entitlements.to_dict()}')\n",
    "\n",
    "pm = PortfolioManager(portfolio.id)\n",
    "pm.set_entitlements(entitlements)"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "## Step 4: Define Portfolio Positions\n",
    "\n",
    "Portfolio positions in Marquee are stored on a holding basis, when means you only upload positions for days where you are rebalancing your portfolio. Take the following set of positions:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "portfolio_position_sets = [\n",
    "    PositionSet(\n",
    "        date=dt.date(day=3, month=5, year=2021),\n",
    "        positions=[\n",
    "            Position(identifier='AAPL UW', quantity=25),\n",
    "            Position(identifier='GS UN', quantity=50)\n",
    "        ]\n",
    "    ),\n",
    "    PositionSet(\n",
    "        date=dt.date(day=1, month=7, year=2021),\n",
    "        positions=[\n",
    "            Position(identifier='AAPL UW', quantity=26),\n",
    "            Position(identifier='GS UN', quantity=51)\n",
    "        ]\n",
    "    )\n",
    "]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "If these positions were to be uploaded correctly, this portfolio would hold 50 shares of GS UN and 25 shares of AAPL UW from May 3, 2021 to June 30, 2021, and it would hold 51 shares of GS UN and 26 shares of AAPL UW from July 1, 2021 to today."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "pm.update_positions(portfolio_position_sets)\n",
    "\n",
    "print(f\"Updated positions for '{portfolio.name}'\")"
   ]
  },
  {
   "cell_type": "markdown",
   "source": [
    "## Step 5: Schedule Reports\n",
    "By default, creating a portfolio will automatically create a corresponding Performance Report for it as well. If you would like to create a Factor Risk Report for it as well, follow the steps [here](../examples/marquee/00_create_factor_risk_report.ipynb). Then, remember to schedule all the portfolio reports."
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "pm.schedule_reports()\n",
    "\n",
    "print('All portfolio reports scheduled.')"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "## Step 6: Update Custom AUM (Optional)\n",
    "The `CustomAUMDataPoint` class is used to represent custom AUM data for a specific date. A list of them can be posted to Marquee using our initialized `PortfolioManager`. If you do not upload custom AUM data for your portfolio and change your portfolio's AUM Source to `Custom AUM`, by default the \"AUM\" (which is used for calculating risk as percent values) will be your portfolio's long exposure."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "performance_report = pm.get_performance_report()\n",
    "performance_report.set_aum_source(RiskAumSource.Custom_AUM)\n",
    "custom_aum = [\n",
    "    CustomAUMDataPoint(date=dt.date(2021, 5, 1), aum=100000),\n",
    "    CustomAUMDataPoint(date=dt.date(2021, 7, 1), aum=200000)\n",
    "]\n",
    "performance_report.upload_custom_aum(custom_aum, clear_existing_data=False)\n",
    "\n",
    "print(f\"Custom AUM for '{portfolio.name} successfully uploaded'\")"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "### You're all set, Congrats! What's next?\n",
    "\n",
    "* [Creating and scheduling a factor risk report](../examples/marquee/00_create_factor_risk_report.ipynb)\n",
    "\n",
    "* [Updating the portfolio with new positions](../tutorials/Update%20Historical%20Portfolio.ipynb)\n",
    "\n",
    "* [Retrieving the portfolio's performance analytics](../tutorials/Pull%20Portfolio%20Performance%20Data.ipynb)\n",
    "\n",
    "* [Retrieving the portfolio's factor risk and attribution analytics](../tutorials/Pull%20Portfolio%20Factor%20Risk%20Data.ipynb)\n",
    "\n",
    "\n",
    "*Other questions? Reach out to the [Portfolio Analytics team](mailto:gs-marquee-analytics-support@gs.com)!*\n"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
